/*
 * Copyright 2006 Berry Crawford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.judo.frontcontroller;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.judo.frontcontroller.exceptions.InvalidMappingException;
import org.judo.frontcontroller.exceptions.URLMappingManager;

public class PrettyURLManager
{
	private static HashMap urlMaps = new HashMap();
	
	public static void load()
	{
		InputStream is = null;
		
		try
		{
			 
			is =(new URLMappingManager().getClass()).getResourceAsStream(
					"/pretty_urls.xml");
			
			SAXBuilder builder = new SAXBuilder();
			Document doc = builder.build(is);
			Element root = doc.getRootElement();
			
			List mappings = root.getChildren();
			
			for (int i=0;i<mappings.size();i++)
			{
				Element mapping = (Element)mappings.get(i);
				
				String url = mapping.getAttributeValue("url_name");
				String mapTo = mapping.getAttributeValue("mapto");
				
				Mapping mappingObj = new Mapping();
				mappingObj.url = url;
				mappingObj.forward = mapTo;
				
				List params = mapping.getChildren();
				
				for (int j=0;j<params.size();j++)
				{
					Element param = (Element)params.get(j);
					String paramName = param.getAttributeValue("name");
					mappingObj.paramNames.add(paramName);
				}
				
				PrettyURLManager.map(url,mappingObj);
			}
		}
		catch(Throwable e)
		{
			System.out.println("[FATAL ERROR]: could not load Simple URL mappings because: "+e);
		}
		finally
		{
			if (is != null)
			{
				try
				{
					is.close();
				} catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void map(String urlName,Mapping mapping)
	{
		urlMaps.put(urlName,mapping);
	}
	
	public static String parsePrettyURL(HttpServletRequest request,String prettyURLBase) throws InvalidMappingException
	{
		String forward = null;
		
		String path = request.getRequestURI();
		
		int size = prettyURLBase.length()+2;
		int baseLocation = path.indexOf("/"+prettyURLBase);
		int start = baseLocation + size;
		
		String actionPath = path.substring(start);
		String pathParts[] = actionPath.split("/");
		String actionName = pathParts[0];
		
		Mapping mapping = (Mapping)urlMaps.get(actionName);
		forward = mapping.forward; 
			
		if (mapping == null)
			throw new InvalidMappingException("The Pretty URL: '"+request.getRequestURI()+"' does not have a defined map '"+actionName+"' in 'pretty_urls.xml' and has not been programatically.");
		
		if (mapping.paramNames.size() != pathParts.length-1)
			throw new InvalidMappingException("Pretty URLs and maps must have the same number of params defined. The Pretty URL: '"+request.getRequestURI()+"' has "+(pathParts.length-1)+" params and the defined map '"+actionName+"' has "+mapping.paramNames.size()+" params defined");
		
		String paramString = "?";
		boolean first = true;
		
		for (int i=1;i<pathParts.length;i++)
		{
			if (first)
				first = false;
			else
				paramString += "&";
				
			String value = pathParts[i];
			String paramName = (String)mapping.paramNames.get(i-1); 
			paramString += paramName+"="+value;
		}
		
		if (forward == null)
			throw new InvalidMappingException("The Pretty URL: '"+request.getRequestURI()+"' does not have a defined map");
		
		
		return forward+paramString;
	}
	
	public static String mappings()
	{
		return urlMaps.toString();
	}
}
